package com.example.studyinbetterlogin.fragment.smallestPathFragment

import android.graphics.Color
import android.graphics.Paint
import com.example.studyinbetterlogin.databinding.FragmentSmallestPathBinding
import com.example.studyinbetterlogin.fragment.BaseFragment
import com.example.studyinbetterlogin.shapes.CircleToCircleLineShape
import com.example.studyinbetterlogin.shapes.PointShape

class SmallestPathFragment : BaseFragment<FragmentSmallestPathBinding>() {
    override fun initBinding(): FragmentSmallestPathBinding {
        return FragmentSmallestPathBinding.inflate(layoutInflater)
    }

    override fun initView() {
        var id = 0
        val thisPaint: Paint = Paint().apply {
            color = Color.WHITE
            strokeWidth = 10f
            style = Paint.Style.STROKE
        }

        mBinding.drawCircle.setOnClickListener {
            val thisShape = PointShape(-100f, -100f, thisPaint)
            thisShape.id = id
            mBinding.drawBoard.loadShape(thisShape)
            mBinding.drawBoard.invalidate()
            id++
        }

        mBinding.LinePaint.setOnClickListener {
            mBinding.drawBoard.setState("isDrawCircleToCircleLine")
        }

        mBinding.button.setOnClickListener {
            val lineShapes = mutableListOf<CircleToCircleLineShape>()
            mBinding.drawBoard.layerManager.mShapes.forEach { shapeList ->
                shapeList.forEach { shape ->
                    if (shape is CircleToCircleLineShape) {
                        lineShapes.add(shape)
                        println("LineShape: id1 = ${shape.id1}, id2 = ${shape.id2}")
                    }
                }
            }

            // 获取用户输入的起点和终点ID
            val pointId1 = mBinding.startPointIdEditText.text.toString().toIntOrNull()
            val pointId2 = mBinding.endPointIdEditText.text.toString().toIntOrNull()

            if (pointId1 == null || pointId2 == null) {
                mBinding.resultTextView.text = "请输入有效的起点和终点ID"
                return@setOnClickListener
            }

            // 使用Dijkstra算法查找最短路径
            val shortestPath = findShortestPath(lineShapes, pointId1, pointId2)

            // 重置所有线段为白色
            lineShapes.forEach { it.mPaint.color = Color.BLUE }

            // 仅将最短路径上的线段标红
            if (shortestPath.isNotEmpty()) {
                val newPaint: Paint = Paint().apply {
                    color = Color.RED
                    strokeWidth = 5f
                    style = Paint.Style.STROKE
                }
                shortestPath.forEach {
                    it.mPaint = newPaint
                }
                mBinding.drawBoard.invalidate()
            } else {
                mBinding.resultTextView.text = "找不到从点 $pointId1 到点 $pointId2 的路径"
            }
        }
    }
    private fun findShortestPath(
        lineShapes: MutableList<CircleToCircleLineShape>,
        startId: Int,
        endId: Int
    ): List<CircleToCircleLineShape> {
        val distances = mutableMapOf<Int, Float>().withDefault { Float.MAX_VALUE }
        val previous = mutableMapOf<Int, CircleToCircleLineShape?>()
        val unvisited = mutableSetOf<Int>()
        val lineMap = mutableMapOf<Int, MutableList<CircleToCircleLineShape>>()

        lineShapes.forEach { shape ->
            lineMap.getOrPut(shape.id1) { mutableListOf() }.add(shape)
            lineMap.getOrPut(shape.id2) { mutableListOf() }.add(shape)
            unvisited.add(shape.id1)
            unvisited.add(shape.id2)
        }
        distances[startId] = 0f

        while (unvisited.isNotEmpty()) {
            val currentId = unvisited.minByOrNull { distances.getValue(it) } ?: break
            unvisited.remove(currentId)

            if (currentId == endId) break

            val currentDistance = distances.getValue(currentId)
            lineMap[currentId]?.forEach { line ->
                val neighborId = if (line.id1 == currentId) line.id2 else line.id1
                if (neighborId in unvisited) {
                    val newDistance = currentDistance + line.length()
                    if (newDistance < distances.getValue(neighborId)) {
                        distances[neighborId] = newDistance
                        previous[neighborId] = line
                    }
                }
            }
        }
        val path = mutableListOf<CircleToCircleLineShape>()
        var currentId: Int? = endId
        while (currentId != null && currentId != startId) {
            val line = previous[currentId] ?: break
            path.add(line)
            currentId = if (line.id1 == currentId) line.id2 else line.id1
        }
        return path.reversed()
    }
    fun CircleToCircleLineShape.length(): Float {
        return Math.sqrt(
            Math.pow((endX - startX).toDouble(), 2.0) + Math.pow((endY - startY).toDouble(), 2.0)
        ).toFloat()
    }
}
